package edu.ksu.cis.android.project31;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.util.Pair;

public class Maze {
	
	private Random random = new Random();
	
	private Space[][] spaces;
	private int rows;
	private int cols;
	private boolean startAssigned = false;
	public Pair<Integer,Integer> start;
	public Pair<Integer,Integer> end;
	
	public Maze(int rows, int cols) {
		this.rows = rows;
		this.cols = cols;
		this.spaces = new Space[rows][cols];
		initSpaces();
		end = getEndPoint();
		generateMaze(end);
	}
	
	private void initSpaces() {
		for(int i = 0; i < rows; i++) {
			for(int j = 0; j < cols; j++) {
				spaces[i][j] = new Space();
			}
		}
	}
	
	public Maze() {
		this(10,10);
	}
	
	public Space[][] getMaze() {
		return spaces;
	}
	
	private void generateMaze(Pair<Integer,Integer> current) {
		System.out.println("\n"+current+"\n"+this.toString());
		
		spaces[current.first][current.second].visited = true;
		List<Pair<Integer,Integer>> neighbors = getListOfNeighbors(current);
		while(neighbors.size() > 0) {
			int nxt = random.nextInt(neighbors.size());
			Pair<Integer,Integer> p = neighbors.get(nxt);
			if(!spaces[p.first][p.second].visited) {
				// Remove the wall (create a path) between current and selected pair
				removeWall(current, p);
				
				// Recurse into generateMaze with selected pair
				generateMaze(p);
			}
			neighbors.remove(nxt);
		}
		if (!startAssigned)
		{
			startAssigned = true;
			spaces[current.first][current.second].start = true;
		}
	}
	
	private void removeWall(Pair<Integer,Integer> one, Pair<Integer,Integer> two) {
		//System.out.println("Removing wall between " + one + " and " + two);
		if(one.first == two.first-1) {
			//System.out.println("Case 1");
			// two is one's bottom neighbor
			spaces[one.first][one.second].bottom = false;
			spaces[two.first][two.second].top = false;
		} else if(one.first == two.first+1) {
			//System.out.println("Case 2");
			// two is one's top neighbor
			spaces[one.first][one.second].top = false;
			spaces[two.first][two.second].bottom = false;
		} else if(one.second == two.second-1) {
			//System.out.println("Case 3");
			// two is one's right neighbor
			spaces[one.first][one.second].right = false;
			spaces[two.first][two.second].left = false;
		} else if(one.second == two.second+1) {
			//System.out.println("Case 4");
			// two is one's left neighbor
			spaces[one.first][one.second].left = false;
			spaces[two.first][two.second].right = false;
		}
	}
	
	public boolean isBlockedH(int one, int two,int col)
	{
		if (one < two) return spaces[col][one].right;
		else if (one > two) return spaces[col][one].left;
		
		return false;
	}
	public boolean isBlockedV(int one, int two,int row)
	{
		if (one < two) return spaces[one][row].bottom;
		else if (one > two) return spaces[one][row].top;
		
		return false;
	}
	
	private List<Pair<Integer,Integer>> getListOfNeighbors(Pair<Integer,Integer> space) {
		List<Pair<Integer,Integer>> list = new ArrayList<Pair<Integer,Integer>>();
		if(space.first != 0) {
			list.add(new Pair<Integer,Integer>(space.first-1, space.second));
		}
		if(space.first != rows-1) {
			list.add(new Pair<Integer,Integer>(space.first+1, space.second));
		}
		if(space.second != 0) {
			list.add(new Pair<Integer,Integer>(space.first, space.second-1));
		}
		if(space.second != cols-1) {
			list.add(new Pair<Integer,Integer>(space.first, space.second+1));
		}
		return list;
	}
	
	private Pair<Integer,Integer> getEndPoint() {
		int r = random.nextInt(rows);
		int c = random.nextInt(cols);
		spaces[r][c].hole = true;
		return new Pair<Integer,Integer>(r,c);
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for(Space[] row : spaces) {
			for(Space col : row) {
				if(col.left) sb.append('|');
				else sb.append(' ');
				if(col.top) {
					if(col.hole) sb.append((char)200);
					else if(col.start) sb.append((char)192);
					else sb.append((char)175);
				}
				else {
					if(col.hole) sb.append('E');
					else if(col.start) sb.append('A');
					else sb.append(' ');
				}
			}
			sb.append('\n');
		}
		return sb.toString();
	}
}
